package com.gzz.orchid.context.domain.rbac.impl;

import com.gzz.orchid.common.boot.mybatis.conditices.QueryCondition;
import com.gzz.orchid.common.core.authorization.UserContextHolder;
import com.gzz.orchid.common.core.exception.BizzException;
import com.gzz.orchid.common.core.util.I18nUtil;
import com.gzz.orchid.context.domain.rbac.IUserRepository;
import com.gzz.orchid.context.domain.rbac.entity.Privilege;
import com.gzz.orchid.context.domain.rbac.entity.UserDo;
import com.gzz.orchid.context.infrastructure.definition.Action;
import com.gzz.orchid.context.infrastructure.definition.Status;
import com.gzz.orchid.context.infrastructure.persistence.entity.sys.SysPrivilegePo;
import com.gzz.orchid.context.infrastructure.persistence.entity.sys.SysUserPo;
import com.gzz.orchid.context.infrastructure.persistence.mapper.sys.SysPrivilegeMapper;
import com.gzz.orchid.context.infrastructure.persistence.mapper.sys.SysUserMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Repository;

import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author higmd
 */
@Slf4j
@Repository
@RequiredArgsConstructor
public class UserRespository implements IUserRepository {
    private final SysUserMapper mapper;
    private final SysPrivilegeMapper privilegeMapper;

    @Override
    public UserDo findByCode(String code) {
        var condit = new QueryCondition();
        SysUserPo po = mapper.selectOneByCondition(condit);
        return Optional.ofNullable(po).map(UserDo::convertFrom).orElse(null);
    }

    @Override
    public List<UserDo> findListByIds(Serializable[] ids) {
        List<SysUserPo> poList = mapper.selectListByIds(ids);
        //
        return poList.stream()
                .map(UserDo::convertFrom)
                .collect(Collectors.toList());
    }

    @Override
    public int batchDelete(Serializable[] ids) {
        var n = mapper.removeByIds(ids);
        // 记录日志log
        log.info("删除用户[{}]成功，删除{}行数据", ids, n);
        return n;
    }

    @Override
    public int batchChangeStatus(Status status, List<UserDo> doList) {
        var po = new SysUserPo();
        po.setStatus(status.getValue());
        po.setUpdatedOn(LocalDateTime.now());
        po.setUpdatedBy(UserContextHolder.getUserCode());
        // 条件
        var condit = new QueryCondition();
        condit.in("id", doList.stream().map(UserDo::getId).toArray());
        var n =mapper.updateByCondition(po, condit);
        // 记录日志log
        log.info("批量修改[{}]角色状态[{}]成功，影响{}行数据", doList.size(), status.getValue(), n);
        return n;
    }

    @Override
    public void save(UserDo userDo) {
        var po = new SysUserPo();
        var n = (Objects.isNull(po.getId()))?mapper.insert(po): mapper.updateById(po);
        // 记录日志log
        log.info("保存用户[{}]成功，影响{}行数据", userDo.getUserName(), n);
    }

    @Override
    public void changePassword(UserDo userDo) {
        var po = new SysUserPo();
        po.setPasswd(userDo.getPasswd());
        po.setSalt(userDo.getSalt());
        po.setUpdatedOn(LocalDateTime.now());
        po.setUpdatedBy(UserContextHolder.getUserCode());
        po.setId(userDo.getId());

        var n = mapper.updateById(po);
        log.info("修改用户[{}]密码，影响{}行数据", userDo.getId(), n);
        if (n <= 0) {
            throw new BizzException(I18nUtil.ofMessage("密码修改失败"));
        }
    }

    @Override
    public void saveGrantPrivilege(Long userId, List<Privilege> privileges) {
        List<SysPrivilegePo> poList = null;
        //privileges.stream().map(p -> SysPrivilegePo.convertFrom(p)).collect(Collectors.toList());
//        privilegeMapper.deleteByCondition(QueryCondition.create(SYS_PRIVILEGE_PO.USER_ID, "in", userId));
//        privilegeMapper.insertBatch(poList);
    }

    @Override
    public void saveRecyclePrivilege(Long userId, List<Privilege> privileges) {
        Map<String, Privilege> privilegeMap = privileges
                .stream()
                .collect(Collectors.toMap(Privilege::getModuleCode, p -> p));
        //
//        List<SysPrivilegePo> poList = privilegeMapper
//                .selectListByCondition(QueryCondition.create(SYS_PRIVILEGE_PO.USER_ID, "=", userId)
//                        .and(QueryCondition.create(SYS_PRIVILEGE_PO.MODULE_CODE, "in", privilegeMap.keySet().toArray())));
        List<SysPrivilegePo> poList = null;
        for (SysPrivilegePo po : poList) {
            var privilege = privilegeMap.get(po.getModuleCode());
            if (Objects.nonNull(privilege)) {
                po.setPurview(privilege.getActions().stream().mapToInt(Action::getValue).sum());
                po.setEffAt(privilege.getValidTime().getBegin());
                po.setExpAt(privilege.getValidTime().getEnd());
                //privilegeMapper.update(po);
            }
        }
        // 追加 append
        List<Privilege> appendPrivilege = privileges
                .stream()
                .filter(item -> poList
                        .stream()
                        .map(SysPrivilegePo::getModuleCode).toList().contains(item.getModuleCode()))
                .toList();
        if (!appendPrivilege.isEmpty()) {
            List<SysPrivilegePo> poList2 = appendPrivilege
                    .stream()
                    .map(item -> {
                        SysPrivilegePo po = new SysPrivilegePo();
                        po.setUserId(userId);
                        po.setModuleCode(item.getModuleCode());
                        po.setPurview(item.getActions().stream().mapToInt(Action::getValue).sum());
                        po.setEffAt(item.getValidTime().getBegin());
                        po.setExpAt(item.getValidTime().getEnd());
                        po.setStatus(0);
                        return po;
                    })
                    .toList();
            //privilegeMapper.insertBatch(poList2);
        }
    }
}
